package com.mgq.algorithm.bit;

/**
 * 使用位运算获取最大值
 */
public class GetMax {
    /**
     * 1变0,0变1
     * 1->0
     * 0->1
     *
     * @param n
     * @return
     */
    public static int flip(int n) {
        return n ^ 1;
    }

    /**
     * n是非负数(正数) 返回1
     * n是负数 返回0
     *
     * @param n
     * @return
     */
    public static int sign(int n) {
        return flip(n >> 31 & 1);
    }

    /**
     * 这个方法无法处理溢出的情况
     *
     * @param a
     * @param b
     * @return
     */
    public static int getMax1(int a, int b) {
        int c = a - b;
        int scA = sign(c); //a-b>0 sca=1   a-b<>>0 sca=1
        int scB = flip(sign(c)); //scb和sca是相反数
        return a * scA + b * scB; //a大,scA为1,scB为0 返回a. b大,scB为1,返回b
    }

    /**
     * 真正比较大小的访问,能够解决溢出的问题
     *
     * @param a
     * @param b
     * @return
     */
    public static int getMax(int a, int b) {
        int c = a - b;
        int sa = sign(a); //a的符号
        int sb = sign(b);//b的符号
        int sc = sign(c);//c的符号
        int difSab = sa ^ sb;//a和b的符号不一样,为1.符号一样,为0
        int sameSab = flip(difSab); //a和b的符号一样为1,不一样为0
        //如果a和b符号不同,返回a的条件是a>0 sa=1 或者a和b符号相同,他们的差值sc为1时返回 (这个加号是表示或者)
        //这里sa和sc相当于是if判断,把条件判断改为了数学表达式
        int returnA = difSab * sa + sameSab * sc; //返回a的条件 a和b的符号相同(a-b)不会溢出 a-b>0 //a和b符号不同, a>0
        int returnB = flip(returnA);
        return a * returnA + b * returnB;
    }

    public static void main(String[] args) {
        int a=100;
        int b = -20;
        System.out.println(getMax(a, b));
    }
}
